package com.hdu.atomic;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class AtomicArray {


    public static void main(String[] args) {
        test(
                () -> new int[10],
                (array) -> array.length,
                (array, index) -> array[index]++,
                (array) -> {
                    System.out.println(Arrays.toString(array));
                }
        );


        test(
                () -> new AtomicIntegerArray(10),
                AtomicIntegerArray::length,
                AtomicIntegerArray::incrementAndGet,
                (array) -> System.out.println(array.toString())
        );
    }

    static <T> void test(
            Supplier<T> arraySupplier,
            Function<T, Integer> getLenFunc,
            BiConsumer<T, Integer> putConsumer,
            Consumer<T> printConsumer
    ) {
        T array = arraySupplier.get();
        int len = getLenFunc.apply(array);
        List<Thread> ts = new ArrayList<>();
        for (int i = 0; i < len; i++) {
            ts.add(new Thread(() -> {
                for (int j = 0; j < 10000; j++) {
                    putConsumer.accept(
                            array,
                            j % len
                    );
                }
            }));
        }

        ts.forEach(Thread::start);
        ts.forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        printConsumer.accept(array);
    }
}
